import java.util.ArrayList;


public class TerminalState extends Node {
	
	private ArrayList<ArrayList<Integer>> states;
	private ArrayList<String> groupOutput;
	private String outputSeq;
	
	public TerminalState(String op, ArrayList<ArrayList<Integer>> st, ArrayList<String> grOp){
		states = st;
		groupOutput = grOp;
		outputSeq = op;
	}
	
	@Override
	public Node ApplyZero() {
		ArrayList<ArrayList<Integer>> newGroups = new ArrayList<ArrayList<Integer>>();
		ArrayList<String> grpOp = new ArrayList<String>();
		for(int i=0; i<states.size(); i++){
			ArrayList<Integer> newZeros = new ArrayList<Integer>();
			ArrayList<Integer> newOnes = new ArrayList<Integer>();
			for(int j=0; j<states.get(i).size(); j++){
				if(output[states.get(i).get(j)][0] == 0 && (!newZeros.contains(nextState[states.get(i).get(j)][0])) ){
					 newZeros.add(nextState[states.get(i).get(j)][0]);
				}else if((!newOnes.contains(nextState[states.get(i).get(j)][0]))&& output[states.get(i).get(j)][0] == 1) 
					newOnes.add(nextState[states.get(i).get(j)][0]);	
			}
			if(!newZeros.isEmpty()){
				newGroups.add(newZeros);
				grpOp.add(groupOutput.get(i)+0);
			}if(!newOnes.isEmpty()){
				newGroups.add(newOnes);
				grpOp.add(groupOutput.get(i)+1);
			}
		}
		return new TerminalState(outputSeq+0, newGroups, grpOp);
	}

	@Override
	public Node ApplyOne() {
		ArrayList<ArrayList<Integer>> newGroups = new ArrayList<ArrayList<Integer>>();
		ArrayList<String> grpOp = new ArrayList<String>();
		for(int i=0; i<states.size(); i++){
			ArrayList<Integer> newZeros = new ArrayList<Integer>();
			ArrayList<Integer> newOnes = new ArrayList<Integer>();
			for(int j=0; j<states.get(i).size(); j++){
				if(output[states.get(i).get(j)][1] == 0 && (!newZeros.contains(nextState[states.get(i).get(j)][1]))){
					 newZeros.add(nextState[states.get(i).get(j)][1]);
				}else if((!newOnes.contains(nextState[states.get(i).get(j)][1]))&& output[states.get(i).get(j)][1] == 1)
					newOnes.add(nextState[states.get(i).get(j)][1]);	
			}
			if(!newZeros.isEmpty()){
				newGroups.add(newZeros);
				grpOp.add(groupOutput.get(i)+0);
			}if(!newOnes.isEmpty()){
				newGroups.add(newOnes);
				grpOp.add(groupOutput.get(i)+1);
			}
		}
		return new TerminalState(outputSeq+1, newGroups, grpOp);
	}

	@Override
	public boolean isTerminated() 
	{
		for(int i=0 ; i< states.size(); i++)
		{
			if(states.get(i).size() != 1)
				return false;
		}
		return true;
	}

	@Override
	public boolean isEqual(Node e) {
		TerminalState e2 = (TerminalState) e;
		ArrayList<ArrayList<Integer>> arrOfE2 = e2.getStatesArray();
		if(states.size() != arrOfE2.size()){
			return false;
		}
		for(int i=0;  i<states.size(); i++){
			int sizeOfThis = states.get(i).size();
			ArrayList<Integer> temp1 = states.get(i);
			if(sizeOfThis >1)
			{
				boolean found = false;
				for(int j=0; j< arrOfE2.size(); j++)
				{
					if(arrOfE2.get(j).size() == sizeOfThis)
					{
						found = true;
						ArrayList<Integer> temp2 = arrOfE2.get(j);
						for(int k=0; k<sizeOfThis ; k++)
						{
							if(!temp2.contains(temp1.get(k)))
								found =false;
						}
						if(found)
							break;
					}
				}
				if(!found)
					return false;
			}
		}
		return true;
	}
	
	public  ArrayList<ArrayList<Integer>> getStatesArray(){
		return states;
	}
	

	@Override
	public String getResult() {
		// TODO Auto-generated method stub
		return outputSeq;
	}

	@Override
	public String[][] getTable() {
		// TODO Auto-generated method stub
		String[][] res = new String[groupOutput.size()][2];
		for(int i=0; i<res.length; i++){
			res[i][1] = groupOutput.get(i);
			res[i][0] = ""+states.get(i).get(0);
		}
		return res;
	}
	@Override
	public String toString()
	{
		return states.toString();
	}
}
